package com.magupe.push.client;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.magupe.push.client.handler.AuthenticationResponseHandler;
import com.magupe.push.client.handler.FileResponseHandler;
import com.magupe.push.client.handler.MessageResponseHandler;
import com.magupe.push.client.handler.RPCMessageResponseHandler;
import com.magupe.push.common.codec.PacketDecoder;
import com.magupe.push.common.codec.PacketEncoder;
import com.magupe.push.common.codec.Spliter;
import com.magupe.push.common.protocol.request.AuthenticationRequestPacket;
import com.magupe.push.common.protocol.request.FileRequestPacket;
import com.magupe.push.common.utils.Constants;
import com.magupe.push.log.util.IdGen;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

public class NettyPushClient{

	protected Logger logger = LoggerFactory.getLogger(NettyPushClient.class);
	
	private static final int MAX_RETRY = 3;
    private static final String HOST = "10.6.190.174";
    private static final int PORT = 7000;
    
	Channel channel;
	
	protected void init() {
    	NioEventLoopGroup workerGroup = new NioEventLoopGroup();
    	
    	Bootstrap bootstrap = new Bootstrap();
        bootstrap
	        .group(workerGroup)
	        .channel(NioSocketChannel.class)
	        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
	        .option(ChannelOption.SO_KEEPALIVE, true)
	        .option(ChannelOption.TCP_NODELAY, true)
	        .handler(new ChannelInitializer<SocketChannel>() {
	            @Override
	            public void initChannel(SocketChannel ch) {
	            	ch.pipeline().addLast(new Spliter());
	                ch.pipeline().addLast(new PacketDecoder());
	                ch.pipeline().addLast(new AuthenticationResponseHandler());
	                ch.pipeline().addLast(new MessageResponseHandler());
	                ch.pipeline().addLast(new RPCMessageResponseHandler());
	                ch.pipeline().addLast(new FileResponseHandler());
	                ch.pipeline().addLast(new PacketEncoder());
	            }
	        });

        ChannelFuture future = connectRetry(bootstrap, HOST, PORT, MAX_RETRY);
        if(future == null) {
        	System.exit(0);
        }
        channel = ((ChannelFuture) future).channel();
	}
    
	protected ChannelFuture connectRetry(Bootstrap bootstrap, String host, int port, int retry) {
        try {
        	return bootstrap.connect(HOST, PORT).sync();
		} catch (Exception e) {
			retry --;
			if(retry <= 0) {
				logger.error("Connect Netty Error", e);
				return null;
			}
			logger.info("retry");
			return connectRetry(bootstrap, host, port, retry);
		}
    }
    
    protected ChannelFuture authentication(String contentId, String secret) {
    	AuthenticationRequestPacket packet = new AuthenticationRequestPacket();
		packet.setContentId(contentId);
		packet.setSecret(secret);
		packet.setSource("client");
		packet.setMsgId(IdGen.snowFlakeId());
		
		return channel.writeAndFlush(packet);
	}

	public static void main(String[] args) throws IOException {
		String contentId = "com.magupe.push";
		String secret = "f988c38b94ec4e6fbf0115f12779ba09";
		
		FileRequestPacket fileRequest = new FileRequestPacket();
		fileRequest.setContentId(contentId);
		fileRequest.setSecret(secret);
		fileRequest.setMsgId(IdGen.snowFlakeId());
		fileRequest.setUserId("123456");
		fileRequest.setSource("client");
		fileRequest.setStartPos(0);
		fileRequest.setPath("C:/Users/Administrator/Desktop/resources/image/1a2fa094e25a03255261a68881188695.jpg");
		
		RandomAccessFile randomAccessFile = new RandomAccessFile(new File(fileRequest.getPath()), "rw");
		randomAccessFile.seek(fileRequest.getStartPos());
		byte[] bytes = new byte[Constants.LAST_LENGTH]; 
		int byteRead = randomAccessFile.read(bytes); // 读取固定长度的数据块到字节数组，并返回写入的字节个数
		fileRequest.setEndPos(byteRead);
		fileRequest.setBytes(bytes);
		randomAccessFile.close();
	
		NettyPushClient client = new NettyPushClient();
		client.init();
		ChannelFuture future = client.authentication(contentId, secret);
		future.addListener(new GenericFutureListener<Future<? super Void>>() {
			@Override
			public void operationComplete(Future<? super Void> future) throws Exception {
				if(future.isSuccess()) {
					client.channel.writeAndFlush(fileRequest);
				}
			}
		});
	}
}
